package vns.client.view;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import vns.client.helper.Helper;
import vns.client.helper.NumericTextBox;
import vns.client.helper.ValueAndName;
import vns.client.presenter.RuleSetPresenter;
import vns.shared.ObjectTypeDTO;
import vns.shared.RuleSetDTO;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.datepicker.client.DateBox;

public class RuleSetUI extends Composite implements RuleSetPresenter.Display {

	private List<String> listStringColumn = new ArrayList<String>();
	private static ObjectTypeUIUiBinder uiBinder = GWT
			.create(ObjectTypeUIUiBinder.class);
	private static int rowSelectedID;
	private List<RuleSetDTO> listRow = new ArrayList<RuleSetDTO>();
	private List<ObjectTypeDTO> listOType = new ArrayList<ObjectTypeDTO>();

	@UiField
	FlexTable flexTable;
	@UiField
	Button btAdd;
	@UiField
	Button btDel;
	@UiField
	Button btUpdate;
	@UiField
	Button btEdit;
	@UiField
	HTMLPanel htmlpanelRuleDetail;

	interface ObjectTypeUIUiBinder extends UiBinder<Widget, RuleSetUI> {
	}

	/*
	 * Constructor
	 */
	public RuleSetUI() {
		initWidget(uiBinder.createAndBindUi(this));
		bind();
	}

	private void bind() {
		/*
		 * Tên các cột
		 */
		listStringColumn.add(""); // OrderCheckBox 0
		listStringColumn.add("Tên quy trình"); // TextBox 1
		listStringColumn.add("Chạy định kì (phút)"); // NumeericTextBox 2
		listStringColumn.add("Thời gian bắt đầu"); // DateTime 3
		listStringColumn.add("Thời gian kết thúc"); // DateTime 4
		listStringColumn.add("Danh sách"); // ListBox 5
		listStringColumn.add("Kiểu"); // ListBox(RULETYPE)5
		listStringColumn.add("Mô tả"); // TextBox 5

		flexTable.setBorderWidth(1);
		flexTable.setCellPadding(2);
		flexTable.setCellSpacing(0);

		/*
		 * FlexTable Even
		 */
		flexTable.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getClickedRow(event);

			}
		});

	}

	public void renderClickedRow() {
		if (rowSelectedID > 0) {
			HTMLTable.RowFormatter rf = flexTable.getRowFormatter();
			rf.addStyleName(rowSelectedID, "vnsClickedRow");
		}
	}

	public void unrenderClickedRow() {
		if (rowSelectedID > 0) {
			HTMLTable.RowFormatter rf = flexTable.getRowFormatter();
			rf.removeStyleName(rowSelectedID, "vnsClickedRow");
		}
	}

	public int getClickedRow(ClickEvent event) {
		int selectedRow = -1;
		HTMLTable.Cell cell = flexTable.getCellForEvent(event);

		if (cell != null) {
			if (cell.getCellIndex() >= 0) {
				selectedRow = cell.getRowIndex();
			}
		}
		swapClickedRow(selectedRow, cell.getCellIndex());
		return selectedRow;
	}

	private void swapClickedRow(int rowNow, int cellindex) {
		if (rowNow != rowSelectedID && rowNow > 0) {
			unrenderClickedRow();
			setRowEnable(rowSelectedID, false);
			rowSelectedID = rowNow;

			renderClickedRow();
			setRowEnable(rowSelectedID, true);
		} else if (rowNow == rowSelectedID && rowNow > 0) {
			if (cellindex == 0) {
				unrenderClickedRow();
				setRowEnable(rowSelectedID, false);
				rowSelectedID = -1;
			}
		}
	}

	/*
	 * Set Row Enable
	 */
	private void setRowEnable(int row, boolean value) {
		if (row <= flexTable.getRowCount() - 1 && row > 0) {
			CheckBox orderCheckBox = (CheckBox) flexTable.getWidget(row, 0);
			orderCheckBox.setValue(value);

			TextBox nameTextBox = (TextBox) flexTable.getWidget(row, 1);
			nameTextBox.setReadOnly(!value);

			NumericTextBox numericTextBox = (NumericTextBox) flexTable
					.getWidget(row, 2);
			numericTextBox.setReadOnly(!value);

			DateBox startDateBox = (DateBox) flexTable.getWidget(row, 3);
			startDateBox.setEnabled(value);

			DateBox endDateBox = (DateBox) flexTable.getWidget(row, 4);
			endDateBox.setEnabled(value);

			ListBox oTypeListBox = (ListBox) flexTable.getWidget(row, 5);
			oTypeListBox.setEnabled(value);

			ListBox rTypeListBox = (ListBox) flexTable.getWidget(row, 6);
			rTypeListBox.setEnabled(value);

			TextBox desTextBox = (TextBox) flexTable.getWidget(row, 7);
			desTextBox.setReadOnly(!value);
		}
	}

	/*
	 * Get Order CheckBox
	 */
	private CheckBox OrderCheckBox(int row, boolean value, boolean enable) {
		final CheckBox cb = new CheckBox();
		cb.setValue(value);
		cb.setEnabled(enable);
		return cb;
	}

	/*************************************************************************/

	/*
	 * Init
	 */

	private void initTableFirst() {
		flexTable.removeAllRows();
		/*
		 * Tên các cột
		 */
		int i = 0;
		for (final String columnName : listStringColumn) {
			flexTable.setHTML(0, i, "<center><b>" + columnName
					+ "</b></center>");
			i++;
		}
	}

	/*
	 * Add Row with Wiget
	 */
	private int addRow(Widget nameTextbox, Widget dinhkiNumericTextBox,
			Widget startDateTime, Widget endDateTime, Widget otypeListBox,
			Widget rtypeListBox, Widget desTextbox) {
		int row = flexTable.getRowCount();
		CheckBox sttCheckbox = OrderCheckBox(row, false, true);
		flexTable.setWidget(row, 0, sttCheckbox);
		flexTable.setWidget(row, 1, nameTextbox);
		flexTable.setWidget(row, 2, dinhkiNumericTextBox);
		flexTable.setWidget(row, 3, startDateTime);
		flexTable.setWidget(row, 4, endDateTime);
		flexTable.setWidget(row, 5, otypeListBox);
		flexTable.setWidget(row, 6, rtypeListBox);
		flexTable.setWidget(row, 7, desTextbox);
		setRowEnable(row, false);
		return row;
	}

	/*
	 * Add Row with data
	 */
	private int addRow(String name, int dinhki, Date starDate, Date endDate,
			String oTypeKey, String rType, String des) {
		int row = flexTable.getRowCount();

		CheckBox sttCheckbox = OrderCheckBox(row, false, true);
		flexTable.setWidget(row, 0, sttCheckbox);

		TextBox nameTextBox = new TextBox();
		nameTextBox.setValue(name);
		flexTable.setWidget(row, 1, nameTextBox);

		NumericTextBox numericTextBox = new NumericTextBox();
		numericTextBox.setText(Integer.toString(dinhki));
		flexTable.setWidget(row, 2, numericTextBox);

		DateBox startDateBox = new DateBox();
		startDateBox.setValue(starDate, false);
		flexTable.setWidget(row, 3, startDateBox);

		DateBox endDateBox = new DateBox();
		endDateBox.setValue(endDate, false);
		flexTable.setWidget(row, 4, endDateBox);

		ListBox oTypeListBox = getOTypeListBox(oTypeKey);
		flexTable.setWidget(row, 5, oTypeListBox);

		ListBox rTypeListBox = getRuleTypeListBox(rType);
		flexTable.setWidget(row, 6, rTypeListBox);

		TextBox desTextBox = new TextBox();
		desTextBox.setValue(des);
		flexTable.setWidget(row, 7, desTextBox);

		setRowEnable(row, false);

		return row;
	}

	private ListBox getRuleTypeListBox(String rType) {
		Helper.get();
		return Helper.get().getListBox(Helper.RULETYPE, rType);
	}

	private ListBox getOTypeListBox(String oTypeKey) {
		return Helper.get().getListBox(
				Helper.get().getListValueAndName(this.listOType), oTypeKey);
	}

	/*
	 * Add Row Empty
	 */
	private int addRow() {
		int row = addRow(new TextBox(), new NumericTextBox(), new DateBox(),
				new DateBox(), getOTypeListBox(null), getRuleTypeListBox(null),
				new TextBox());
		setRowEnable(row, false);
		return row;
	}

	/*
	 * Remove selected Row
	 */
	private void removeRow() {
		if (rowSelectedID > 0) {
			flexTable.removeRow(rowSelectedID);
			int remvIndex = Helper.getIndexByRow(rowSelectedID, listRow.size());
			if (remvIndex != -1) {
				listRow.remove(remvIndex);
			}
			rowSelectedID = -1;
		} else if (rowSelectedID == -1)
			Window.alert("Chọn hàng cần xóa!");
		else
			Window.alert("Không xóa kiểu cơ bản!");
	}

	/*
	 * Update all rows
	 */
	private void updateRow() {
		for (int i = 1; i < listRow.size(); i++) {
			int index = Helper.getIndexByRow(i, listRow.size());

			TextBox nameTextBox = (TextBox) flexTable.getWidget(i, 1);

			NumericTextBox dinhkiNumericTextBox = (NumericTextBox) flexTable
					.getWidget(i, 2);
			int priodicTime = 0;
			if (dinhkiNumericTextBox.getValue() != "")
				priodicTime = Integer.parseInt(dinhkiNumericTextBox.getValue());
			DateBox startDateBox = (DateBox) flexTable.getWidget(i, 3);
			Date startDate = startDateBox.getValue();

			DateBox endDateBox = (DateBox) flexTable.getWidget(i, 4);
			Date endDate = endDateBox.getValue();

			ListBox oTypeListBox = (ListBox) flexTable.getWidget(i, 5);
			String otypeKey = oTypeListBox.getValue(oTypeListBox
					.getSelectedIndex());

			ListBox rTypeListBox = (ListBox) flexTable.getWidget(i, 6);
			String ruletype = rTypeListBox.getValue(rTypeListBox
					.getSelectedIndex());

			TextBox desTextBox = (TextBox) flexTable.getWidget(i, 7);

			listRow.get(index).setName(nameTextBox.getValue());
			listRow.get(index).setPoriodicTime(priodicTime);
			listRow.get(index).setBeginTime(startDate);
			listRow.get(index).setEndTime(endDate);
			listRow.get(index).setoTypeKey(otypeKey);
			listRow.get(index).setRuleType(ruletype);
			listRow.get(index).setDescribe(desTextBox.getValue());
		}
		if (flexTable.getRowCount() - 1 > listRow.size()) {
			for (int row = listRow.size() + 1; row < flexTable.getRowCount(); row++) {
				TextBox nameTextBox = (TextBox) flexTable.getWidget(row, 1);

				NumericTextBox dinhkiNumericTextBox = (NumericTextBox) flexTable
						.getWidget(row, 2);
				int priodicTime = 0;
				if (dinhkiNumericTextBox.getValue() != "")
					priodicTime = Integer.parseInt(dinhkiNumericTextBox
							.getValue());

				DateBox startDateBox = (DateBox) flexTable.getWidget(row, 3);
				Date startDate = startDateBox.getValue();

				DateBox endDateBox = (DateBox) flexTable.getWidget(row, 4);
				Date endDate = endDateBox.getValue();

				ListBox oTypeListBox = (ListBox) flexTable.getWidget(row, 5);
				String otypeKey = oTypeListBox.getValue(oTypeListBox
						.getSelectedIndex());

				ListBox rTypeListBox = (ListBox) flexTable.getWidget(row, 6);
				String ruletype = rTypeListBox.getValue(rTypeListBox
						.getSelectedIndex());

				TextBox desTextBox = (TextBox) flexTable.getWidget(row, 7);

				RuleSetDTO o = new RuleSetDTO(null, nameTextBox.getValue(),
						priodicTime, startDate, endDate, otypeKey, ruletype,
						desTextBox.getValue());
				listRow.add(o);
			}
		}
	}

	/*
	 * Event
	 */

	@UiHandler("btAdd")
	void onBtAddClick(ClickEvent event) {
		addRow();
	}

	@UiHandler("btEdit")
	void onBtEditClick(ClickEvent event) {
		// editRow();
		// TODO
	}

	@UiHandler("btUpdate")
	void onBtUpdateClick(ClickEvent event) {
		updateRow();
	}

	@UiHandler("btDel")
	void onBtDelClick(ClickEvent event) {
		removeRow();
	}

	@Override
	public Button getUpdateButton() {
		return btUpdate;
	}

	@Override
	public Button getEditButton() {
		return btEdit;
	}

	@Override
	public ArrayList<RuleSetDTO> getListRow() {
		return (ArrayList<RuleSetDTO>) listRow;
	}

	@Override
	public boolean setListRow(List<RuleSetDTO> listRow) {
		this.listRow = listRow;
		return true;
	}

	@Override
	public void render() {
		rowSelectedID = -1;
		initTableFirst();
		for (final RuleSetDTO o : this.listRow) {
			addRow(o.getName(), o.getPoriodicTime(), o.getBeginTime(),
					o.getEndTime(), o.getoTypeKey(), o.getRuleType(),
					o.getDescribe());
		}
	}

	@Override
	public Widget asWidget() {
		return this;
	}

	@Override
	public List<ObjectTypeDTO> getListOType() {
		return this.listOType;
	}

	@Override
	public void setListOType(List<ObjectTypeDTO> list) {
		this.listOType = list;

	}

	@Override
	public RuleSetDTO getCurrentRuleSetDTO() {
		if (rowSelectedID > 0 && rowSelectedID < flexTable.getRowCount())
			return listRow.get(Helper.getIndexByRow(rowSelectedID,
					listRow.size()));
		else {
			Window.alert("Chưa chọn hàng!");
			return null;
		}
	}

}
